package cn.shop.front.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.shop.front.async.ProcessOrderAsync;
import cn.shop.front.entity.order.ServiceCharge;
import cn.shop.front.entity.payModule.FkNotifyReq;
import cn.shop.front.entity.payModule.NotifyReq;
import cn.shop.front.mapper.FrontUserMapper;
import cn.shop.front.service.*;
import cn.shop.front.service.message.MessageUtil;
import cn.shop.msgs.OrderMsg;
import cn.shop.transcation.backPaymentChannelModule.entity.BackPaymentChannel;
import cn.shop.transcation.backSetting.entity.BackSetting;
import cn.shop.transcation.detail.entity.FundDetail;
import cn.shop.transcation.detail.mapper.FundDetailMapper;
import cn.shop.transcation.frontUserModule.FrontUser;
import cn.shop.transcation.merchantRateModule.entity.MerchantRate;
import cn.shop.transcation.merchantRateModule.mapper.MerchantRateMapper;
import cn.shop.transcation.merchantUser.mapper.MerchantUserMapper;
import cn.shop.transcation.merchantUser.mapper.entity.MerchantUser;
import cn.shop.transcation.order.entity.Order;
import cn.shop.transcation.order.entity.OrderFrozenAmount;
import cn.shop.transcation.order.entity.OrderRate;
import cn.shop.transcation.order.mapper.OrderMapper;
import cn.shop.transcation.order.mapper.OrderRateMapper;
import cn.shop.transcation.rechargerecord.entity.Record;
import cn.shop.transcation.rechargerecord.mapper.RecordMapper;
import cn.shop.utils.*;
import cn.shop.utils.constant.SystemSettingConstant;
import cn.shop.utils.enums.OrderStatus;
import cn.shop.utils.enums.TransactionState;
import cn.shop.utils.exception.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class NotifyServiceImpl implements NotifyService {

	@Resource
	private OrderMapper orderMapper;

	@Resource
	private MerchantUserMapper merchantUserMapper;
	@Resource
	private MerchantRateMapper merchantRateMapper;

	@Resource
	private OrderRateMapper orderRateMapper;

	@Resource
	private ProcessOrderAsync processOrderAsync;

	@Resource
	private FrontUserMapper frontUserMapper;

	@Resource
	private RecordMapper recordMapper;

	@Resource
	private FundDetailMapper fundDetailMapper;

	@Resource
	private RedissonClient redissonClient;

	@Resource
	private MessageUtil messageUtil;

	@Resource
	private BackSettingService backSettingService;
	@Resource
	private OrderFrozenAmountService orderFrozenAmountService;
	@Resource
	private BackPaymentChannelService channelService;

	/**
	 * 支付回调
	 *
	 * @param payCallback 回调参数
	 * @return 返回结果
	 */
	@Override
	public String notify(NotifyReq payCallback, String alias) {
		RLock lock = redissonClient.getLock("notify:" + payCallback.getOrder_id());
		try {
			if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
				LambdaQueryWrapper<Record> query = Wrappers.lambdaQuery();
				query.eq(Record::getId, payCallback.getOut_trade_no()).ne(Record::getState, TransactionState.CANCELLED);
				Record record = recordMapper.selectOne(query);
				//校验订单
				if (record == null) {
					log.error("充值订单:{} , 支付订单:{}, 订单无效", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "fail";
				}
				BackPaymentChannel channel = channelService.getById(record.getChannelId());
				if (channel == null || channel.getType() == null
						|| StrUtil.hasBlank(channel.getSecret())
						|| channel.getMerchantNumber() == null) {
					throw new ServiceException("支付方式错误");
				}
				Dict dict = Dict.create();
				dict.set("amount", payCallback.getAmount()).
						set("out_trade_no", payCallback.getOut_trade_no()).
						set("order_pay", payCallback.getOrder_pay()).
						set("merchant_id", payCallback.getMerchant_id()).
						set("order_id", payCallback.getOrder_id());
				//校验签名
				if (ObjectUtil.notEqual(PayUtil.getSignToken(dict, channel.getSecret()), payCallback.getCode())) {
					log.error("充值订单:{} , 支付订单:{}, 回调签名认证失败", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "fail";
				}
				// 订单已经处理过 , 直接返回success
				if (record.getState().getCode() >= TransactionState.COMPLETED.getCode()) {
					log.info("充值订单:{} , 支付订单:{}, 充值成功", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "SUCCESS";
				}
				//校验金额
				if (!NumberUtil.equals(payCallback.getAmount(), NumberUtil.mul(record.getAmount(), 100))) {
					// throw new ServiceException("付款金额与订单金额不符");
					log.error("充值订单:{} , 支付订单:{}, 付款金额与订单金额不符", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "FAIL";
				}

				// 修改充值状态
				record.setState(TransactionState.COMPLETED);
				recordMapper.updateById(record);
				processOrderAsync.processOrder(payCallback, record, channel, alias);
			} else {
				log.error("充值订单:{} , 支付订单:{}, 正在处理中", payCallback.getOut_trade_no(), payCallback.getOrder_id());
				return "fail";
			}
		} catch (Exception e) {
			log.error("充值订单:{} , 支付订单:{}, 支付回调失败,错误信息 :{} ", payCallback.getOut_trade_no(), payCallback.getOrder_id(), e.getMessage());
			return "FAIL";
		} finally {
			if (lock.isLocked() && lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
		log.info("充值订单:{} , 支付订单:{}, 支付回调处理完成", payCallback.getOut_trade_no(), payCallback.getOrder_id());
		return "SUCCESS";
	}

	/**
	 * 购买回调
	 *
	 * @param payCallback 回调参数
	 * @return 返回结果
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String orderNotify(NotifyReq payCallback, Long channelId, String alias) {
		RLock lock = redissonClient.getLock("notify:" + payCallback.getOrder_id());
		try {
			if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
				LambdaQueryWrapper<Order> query = Wrappers.lambdaQuery();
				query.eq(Order::getId, payCallback.getOut_trade_no()).eq(Order::getStatus, OrderStatus.TRADING);
				Order order = orderMapper.selectOne(query);
				//校验订单
				if (order == null) {
					log.error("交易订单:{} , 支付订单:{}, 订单无效", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "fail";
				}
				BackPaymentChannel channel = channelService.getById(channelId);
				if (channel == null || channel.getType() == null
						|| StrUtil.hasBlank(channel.getSecret())
						|| channel.getMerchantNumber() == null) {
					throw new ServiceException("支付方式错误");
				}
				Dict dict = Dict.create();
				dict.set("amount", payCallback.getAmount()).
						set("out_trade_no", payCallback.getOut_trade_no()).
						set("order_pay", payCallback.getOrder_pay()).
						set("merchant_id", payCallback.getMerchant_id()).
						set("order_id", payCallback.getOrder_id());
				//校验签名
				if (ObjectUtil.notEqual(PayUtil.getSignToken(dict, channel.getSecret()), payCallback.getCode())) {
					log.error("交易订单:{} , 支付订单:{}, 回调签名认证失败", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "fail";
				}
				// 订单已经处理过 , 直接返回success
				if (order.getStatus() == OrderStatus.COMPLETED) {
					log.info("交易订单:{} , 支付订单:{}, 支付成功", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "SUCCESS";
				}

				//计算分成
				// 查询商户的分成比例，分成规则
				Order update = new Order();
				update.setId(order.getId());
				update.setStatus(OrderStatus.COMPLETED);
				update.setDealTime(LocalDateTime.now());
				orderMapper.updateById(update);
				FrontUser buyer = frontUserMapper.selectById(order.getBuyerId());
				FrontUser seller = frontUserMapper.selectById(order.getSellerId());BigDecimal rate = BigDecimal.ZERO;
				BigDecimal amount = Convert.toBigDecimal(order.getAmount());
				if (channel.getRate() != null) {
					BigDecimal charges = channel.getRate().divide(new BigDecimal(100), 4, RoundingMode.CEILING);
					if (charges.compareTo(BigDecimal.ZERO) > 0) {
						rate = amount.multiply(charges);
					}
				}
				String channelName = channel.getType().getDescription() + "#" + channel.getName();
				processOrder(order, channelName, buyer, seller, rate, alias, true);
				receive(order);
			} else {
				log.error("充值订单:{} , 支付订单:{}, 正在处理中", payCallback.getOut_trade_no(), payCallback.getOrder_id());
				return "fail";
			}
		} catch (Exception e) {
			log.error("交易订单:{} , 支付订单:{}, 支付回调失败,错误信息 :{} ", payCallback.getOut_trade_no(), payCallback.getOrder_id(), e.getMessage());
			return "FAIL";
		}
		log.info("交易订单:{} , 支付订单:{}, 支付回调处理完成", payCallback.getOut_trade_no(), payCallback.getOrder_id());
		return "SUCCESS";
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public String orderNotifyBatch(NotifyReq payCallback, Long channelId, String alias) {
		RLock lock = redissonClient.getLock("notify:" + payCallback.getOrder_id());
		try {
			if (lock.tryLock(0, 60, TimeUnit.SECONDS)) {
				BackPaymentChannel channel = channelService.getById(channelId);
				if (channel == null || channel.getType() == null
						|| StrUtil.hasBlank(channel.getSecret())
						|| channel.getMerchantNumber() == null) {
					throw new ServiceException("支付方式错误");
				}
				RBucket<String> bucket = redissonClient.getBucket("buy:" + payCallback.getOut_trade_no());
				String ids = bucket.get();
				if (StrUtil.isBlank(ids)) {
					log.error("交易订单:{} , 支付订单:{}, 订单无效", "buy:" + payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "fail";
				}
				List<String> orderIds = Arrays.asList(ids.split(","));
				List<Order> list = orderMapper.selectList(Wrappers.<Order>lambdaQuery()
						.in(Order::getId, orderIds)
						.eq(Order::getStatus, OrderStatus.TRADING));
				//校验订单
				if (CollectionUtil.isEmpty(list)) {
					log.error("交易订单:{} , 支付订单:{}, 订单无效 {}", "buy:" + payCallback.getOut_trade_no(), payCallback.getOrder_id(), list);
					return "fail";
				}
				Dict dict = Dict.create();
				dict.set("amount", payCallback.getAmount()).
						set("out_trade_no", payCallback.getOut_trade_no()).
						set("order_pay", payCallback.getOrder_pay()).
						set("merchant_id", payCallback.getMerchant_id()).
						set("order_id", payCallback.getOrder_id());
				//校验签名
				if (ObjectUtil.notEqual(PayUtil.getSignToken(dict, channel.getSecret()), payCallback.getCode())) {
					log.error("交易订单:{} , 支付订单:{}, 回调签名认证失败", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "fail";
				}
				// 订单已经处理过 , 直接返回success
				list = list.stream().filter(o -> o.getStatus() != OrderStatus.COMPLETED).collect(Collectors.toList());
				if (CollectionUtil.isEmpty(list)) {
					log.info("交易订单:{} , 支付订单:{}, 支付成功", payCallback.getOut_trade_no(), payCallback.getOrder_id());
					return "SUCCESS";
				}
				FrontUser buyer = null;
				for (Order order : list) {
					//计算分成
					// 查询商户的分成比例，分成规则
					Order update = new Order();
					update.setId(order.getId());
					update.setStatus(OrderStatus.COMPLETED);
					update.setDealTime(LocalDateTime.now());
					orderMapper.updateById(update);
					if (buyer == null || !buyer.getId().equals(order.getBuyerId())) {
						buyer = frontUserMapper.selectById(order.getBuyerId());
					}
					FrontUser seller = frontUserMapper.selectById(order.getSellerId());BigDecimal rate = BigDecimal.ZERO;
					BigDecimal amount = Convert.toBigDecimal(order.getAmount());
					if (channel.getRate() != null) {
						BigDecimal charges = channel.getRate().divide(new BigDecimal(100), 4, RoundingMode.CEILING);
						if (charges.compareTo(BigDecimal.ZERO) > 0) {
							rate = amount.multiply(charges);
						}
					}
					String channelName = channel.getType().getDescription() + "#" + channel.getName();
					processOrder(order, channelName, buyer, seller, rate, alias, true);
				}
				bucket.delete();
				for (Order order : list) {
					receive(order);
				}
			} else {
				log.error("充值订单:{} , 支付订单:{}, 正在处理中", payCallback.getOut_trade_no(), payCallback.getOrder_id());
				return "fail";
			}
		} catch (Exception e) {
			log.error("交易订单:{} , 支付订单:{}, 支付回调失败,错误信息 :{} ", payCallback.getOut_trade_no(), payCallback.getOrder_id(), e.getMessage());
			return "FAIL";
		}
		log.info("交易订单:{} , 支付订单:{}, 支付回调处理完成", payCallback.getOut_trade_no(), payCallback.getOrder_id());
		return "SUCCESS";
	}


	@Override
	public String fkNotify(FkNotifyReq payCallback, String alias) {
		RLock lock = redissonClient.getLock("notify:" + payCallback.getRequestId());
		try {
			if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
				LambdaQueryWrapper<Record> query = Wrappers.lambdaQuery();
				query.eq(Record::getId, payCallback.getRequestId()).ne(Record::getState, TransactionState.CANCELLED);
				Record record = recordMapper.selectOne(query);
				//校验订单
				if (record == null) {
					log.error("充值订单:{} , 订单无效", payCallback.getRequestId());
					return "SUCCESS";
				}
				BackPaymentChannel channel = channelService.getById(record.getChannelId());
				if (channel == null || channel.getType() == null
						|| StrUtil.hasBlank(channel.getSecret())
						|| channel.getMerchantNumber() == null) {
					throw new ServiceException("支付方式错误");
				}
				Dict dict = Dict.create();
				dict.set("amount", payCallback.getAmount()).
						set("requestId", payCallback.getRequestId()).
						set("orderId", payCallback.getOrderId()).
						set("status", payCallback.getStatus()).
						set("merchantId", payCallback.getMerchantId());
				//校验签名
				if (ObjectUtil.notEqual(PayUtil.getSignToken(dict, channel.getSecret()), payCallback.getCode())) {
					log.error("充值订单:{} , 支付订单:{}, 回调签名认证失败", payCallback.getRequestId(), payCallback.getOrderId());
					return "SUCCESS";
				}
				// 订单已经处理过 , 直接返回success
				if (record.getState().getCode() >= TransactionState.COMPLETED.getCode()) {
					log.info("充值订单:{} , 支付订单:{}, 充值成功", payCallback.getRequestId(), payCallback.getOrderId());
					return "SUCCESS";
				}
				//校验金额
				if (!NumberUtil.equals(payCallback.getAmount(), NumberUtil.mul(record.getAmount(), 100))) {
					// throw new ServiceException("付款金额与订单金额不符");
					log.error("充值订单:{} , 支付订单:{}, 付款金额与订单金额不符", payCallback.getRequestId(), payCallback.getOrderId());
					return "SUCCESS";
				}
				if (!"SUCCESS".equals(payCallback.getStatus())) {
					log.error("充值订单:{} , 支付订单:{}, 回调返回状态失败", payCallback.getRequestId(), payCallback.getOrderId());
					return "fail";
				}
				// 修改充值状态
				record.setState(TransactionState.COMPLETED);
				recordMapper.updateById(record);
				processOrderAsync.processOrder(record, channel, alias);
			} else {
				log.error("充值订单:{} , 支付订单:{}, 正在处理中", payCallback.getRequestId(), payCallback.getOrderId());
				return "SUCCESS";
			}
		} catch (Exception e) {
			log.error("充值订单:{} , 支付订单:{}, 支付回调失败,错误信息 :{} ", payCallback.getRequestId(), payCallback.getOrderId(), e.getMessage());
			return "fail";
		} finally {
			if (lock.isLocked() && lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
		log.info("充值订单:{} , 支付订单:{}, 支付回调处理完成", payCallback.getRequestId(), payCallback.getOrderId());
		return "SUCCESS";
	}

	@Override
	public String fkOrderNotify(FkNotifyReq payCallback, Long channelId, String alias) {
		RLock lock = redissonClient.getLock("notify:" + payCallback.getRequestId());
		try {
			if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
				LambdaQueryWrapper<Order> query = Wrappers.lambdaQuery();
				query.eq(Order::getId, payCallback.getRequestId()).eq(Order::getStatus, OrderStatus.TRADING);
				Order order = orderMapper.selectOne(query);
				//校验订单
				if (order == null) {
					log.error("交易订单:{} , 订单无效", payCallback.getRequestId());
					return "fail";
				}
				BackPaymentChannel channel = channelService.getById(channelId);
				if (channel == null || channel.getType() == null
						|| StrUtil.hasBlank(channel.getSecret())
						|| channel.getMerchantNumber() == null) {
					throw new ServiceException("支付方式错误");
				}
				Dict dict = Dict.create();
				dict.set("amount", payCallback.getAmount()).
						set("requestId", payCallback.getRequestId()).
						set("orderId", payCallback.getOrderId()).
						set("status", payCallback.getStatus()).
						set("merchantId", payCallback.getMerchantId());
				//校验签名
				if (ObjectUtil.notEqual(PayUtil.getSignToken(dict, channel.getSecret()), payCallback.getCode())) {
					log.error("交易订单:{} , 支付订单:{}, 回调签名认证失败", payCallback.getRequestId(), payCallback.getOrderId());
					return "fail";
				}
				// 订单已经处理过 , 直接返回success
				if (order.getStatus() == OrderStatus.COMPLETED) {
					log.info("交易订单:{} , 支付订单:{}, 支付成功", payCallback.getRequestId(), payCallback.getOrderId());
					return "SUCCESS";
				}

				//计算分成
				// 查询商户的分成比例，分成规则
				Order update = new Order();
				update.setId(order.getId());
				update.setStatus(OrderStatus.COMPLETED);
				update.setDealTime(LocalDateTime.now());
				orderMapper.updateById(update);
				FrontUser buyer = frontUserMapper.selectById(order.getBuyerId());
				FrontUser seller = frontUserMapper.selectById(order.getSellerId());BigDecimal rate = BigDecimal.ZERO;
				BigDecimal amount = Convert.toBigDecimal(order.getAmount());
				if (channel.getRate() != null) {
					BigDecimal charges = channel.getRate().divide(new BigDecimal(100), 4, RoundingMode.CEILING);
					if (charges.compareTo(BigDecimal.ZERO) > 0) {
						rate = amount.multiply(charges);
					}
				}
				String channelName = channel.getType().getDescription() + "#" + channel.getName();
				processOrder(order, channelName, buyer, seller, rate, alias, true);
				receive(order);
			} else {
				log.error("充值订单:{} , 支付订单:{}, 正在处理中", payCallback.getRequestId(), payCallback.getOrderId());
				return "fail";
			}
		} catch (Exception e) {
			log.error("交易订单:{} , 支付订单:{}, 支付回调失败,错误信息 :{} ", payCallback.getRequestId(), payCallback.getOrderId(), e.getMessage());
			return "FAIL";
		}
		log.info("交易订单:{} , 支付订单:{}, 支付回调处理完成", payCallback.getRequestId(), payCallback.getOrderId());
		return "SUCCESS";
	}

	@Override
	public String fkOrderNotifyBatch(FkNotifyReq payCallback, Long channelId, String alias) {
		RLock lock = redissonClient.getLock("notify:" + payCallback.getRequestId());
		try {
			if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
				BackPaymentChannel channel = channelService.getById(channelId);
				if (channel == null || channel.getType() == null
						|| StrUtil.hasBlank(channel.getSecret())
						|| channel.getMerchantNumber() == null) {
					throw new ServiceException("支付方式错误");
				}
				RBucket<String> bucket = redissonClient.getBucket("buy:" + payCallback.getRequestId());
				String ids = bucket.get();
				if (StrUtil.isBlank(ids)) {
					log.error("交易订单:{} , 订单无效", "buy:" + payCallback.getRequestId());
					return "fail";
				}
				List<String> orderIds = Arrays.asList(ids.split(","));
				List<Order> list = orderMapper.selectList(Wrappers.<Order>lambdaQuery()
						.in(Order::getId, orderIds)
						.eq(Order::getStatus, OrderStatus.TRADING));
				//校验订单
				if (CollectionUtil.isEmpty(list)) {
					log.error("交易订单:{}, 订单无效 {}", "buy:" + payCallback.getRequestId(), list);
					return "fail";
				}
				Dict dict = Dict.create();
				dict.set("amount", payCallback.getAmount()).
						set("requestId", payCallback.getRequestId()).
						set("orderId", payCallback.getOrderId()).
						set("status", payCallback.getStatus()).
						set("merchantId", payCallback.getMerchantId());
				//校验签名
				if (ObjectUtil.notEqual(PayUtil.getSignToken(dict, channel.getSecret()), payCallback.getCode())) {
					log.error("交易订单:{} , 支付订单:{}, 回调签名认证失败", payCallback.getRequestId(), payCallback.getOrderId());
					return "fail";
				}
				// 订单已经处理过 , 直接返回success
				list = list.stream().filter(o -> o.getStatus() != OrderStatus.COMPLETED).collect(Collectors.toList());
				if (CollectionUtil.isEmpty(list)) {
					log.info("交易订单:{} , 支付订单:{}, 支付成功", payCallback.getRequestId(), payCallback.getOrderId());
					return "SUCCESS";
				}
				FrontUser buyer = null;
				for (Order order : list) {
					//计算分成
					// 查询商户的分成比例，分成规则
					Order update = new Order();
					update.setId(order.getId());
					update.setStatus(OrderStatus.COMPLETED);
					update.setDealTime(LocalDateTime.now());
					orderMapper.updateById(update);
					if (buyer == null || !buyer.getId().equals(order.getBuyerId())) {
						buyer = frontUserMapper.selectById(order.getBuyerId());
					}
					FrontUser seller = frontUserMapper.selectById(order.getSellerId());BigDecimal rate = BigDecimal.ZERO;
					BigDecimal amount = Convert.toBigDecimal(order.getAmount());
					if (channel.getRate() != null) {
						BigDecimal charges = channel.getRate().divide(new BigDecimal(100), 4, RoundingMode.CEILING);
						if (charges.compareTo(BigDecimal.ZERO) > 0) {
							rate = amount.multiply(charges);
						}
					}
					String channelName = channel.getType().getDescription() + "#" + channel.getName();
					processOrder(order, channelName, buyer, seller, rate, alias, true);
				}
				bucket.delete();
				for (Order order : list) {
					receive(order);
				}
			} else {
				log.error("充值订单:{} , 支付订单:{}, 正在处理中", payCallback.getRequestId(), payCallback.getOrderId());
				return "fail";
			}
		} catch (Exception e) {
			log.error("交易订单:{} , 支付订单:{}, 支付回调失败,错误信息 :{} ", payCallback.getRequestId(), payCallback.getOrderId(), e.getMessage());
			return "FAIL";
		}
		log.info("交易订单:{} , 支付订单:{}, 支付回调处理完成", payCallback.getRequestId(), payCallback.getOrderId());
		return "SUCCESS";
	}

	private void setOrderFrozenAmount(BigDecimal sellerShare, Order order, int hour) {
		LocalDateTime now = LocalDateTime.now();
		OrderFrozenAmount frozenAmount = new OrderFrozenAmount();
		frozenAmount.setAmount(sellerShare);
		frozenAmount.setOrderId(order.getId());
		frozenAmount.setUserId(order.getSellerId());
		frozenAmount.setCreateTime(now);
		frozenAmount.setDeadTime(now.plusHours(hour));

		boolean success = orderFrozenAmountService.save(frozenAmount);
		if (!success) {
			log.warn("写入转化表失败, {}", order);
			throw new ServiceException("购买失败");
		}
	}

	private void receive(Order order) {
		Order update = new Order();
		update.setId(order.getId());
		update.setReceived(true);
		long count = orderMapper.updateById(update);
		if (count > 0) { //给消息队列发送购买成功的消息
			try {
				messageUtil.sendMessage(OrderMsg.TOPIC, OrderMsg.TAG, OrderMsg.start().id(order.getId()).time(LocalDateTime.now()).status(OrderStatus.COMPLETED));
			} catch (Exception e) {
				log.warn("发送购买消息错误 {}", order, e);
			}
		}
	}

	private FundDetail createFundDetail(FrontUser user, Order order, BigDecimal merchantShare, BigDecimal platformShare, BigDecimal sellerShare, LocalDateTime now) {
		FundDetail detail = new FundDetail();
		if (user != null) {
			detail.setPlayerAccount(user.getAccount());
			detail.setPlayerId(user.getId());
		}
		detail.setGoods(order.getGoods());
		detail.setAmount(order.getAmount());
		detail.setMerchantShare(merchantShare);
		detail.setAgencyShare(new BigDecimal("0"));
		detail.setPlatformShare(platformShare);
		detail.setSellerShare(sellerShare);
		detail.setOrderId(order.getId());
		detail.setDealTime(now);
		detail.setUid(order.getUid());
		return detail;
	}

	private void processOrder(Order order, String channelName, FrontUser buyer, FrontUser seller, BigDecimal channelShare, String alias, boolean isScan) {
		ServiceCharge charge = getCharge(order);
		MerchantUser merchantUser = merchantUserMapper.selectById(order.getUid());
		BigDecimal platformShare, merchantShare, sellerShare;
		BigDecimal conversionUnit = BigDecimal.valueOf(100);
		BigDecimal p_rate = NumberUtil.div(charge.getChargeRate (), conversionUnit); //平台浮动费率
		BigDecimal m_rage = NumberUtil.div(charge.getRateAdditional(), conversionUnit); //商户浮动费率
		if (charge.getSingleType() && charge.getRateType()) {//方式一，全从商户扣
			sellerShare = order.getAmount();
			platformShare = NumberUtil.mul(order.getAmount(), p_rate).add(charge.getChargeSingle());
			merchantShare = BigDecimal.ZERO;
		} else if (!charge.getRateType() && !charge.getSingleType()) { //方式二，全从玩家扣
			merchantShare =  NumberUtil.mul(order.getAmount(), m_rage).add(charge.getSingleAdditional());
			platformShare = NumberUtil.mul(order.getAmount(), p_rate).add(charge.getChargeSingle());
			sellerShare = order.getAmount().subtract(merchantShare).subtract(platformShare);
		} else if (!charge.getRateType() && charge.getSingleType()) { //方式三，金额从玩家口，单笔从商户扣
			BigDecimal m_charge = NumberUtil.mul(order.getAmount(), m_rage); //商户浮动收益
			BigDecimal p_charge = NumberUtil.mul(order.getAmount(), p_rate); //平台基本收益
			sellerShare = order.getAmount().subtract(m_charge).subtract(p_charge);
			platformShare = p_charge.add(charge.getChargeSingle());
			merchantShare = m_charge;
		} else {//方式三，金额从商户扣，单笔从玩家扣
			BigDecimal p_charge = NumberUtil.mul(order.getAmount(), p_rate); //平台基本收益
			sellerShare = order.getAmount().subtract(charge.getSingleAdditional()).subtract(charge.getChargeSingle());
			platformShare = p_charge.add(charge.getChargeSingle());
			merchantShare = charge.getRateAdditional();
		}
		log.info("订单 {} 的结算信息：{}，总价：{}，平台收益：{}，商户收益：{}，玩家收益：{}", order, charge, order.getAmount(), platformShare, merchantShare, sellerShare);
		LocalDateTime now = LocalDateTime.now();
		//商户添加余额
		MerchantUser newMerchantUser = new MerchantUser();
		newMerchantUser.setId(merchantUser.getId());
		LambdaUpdateWrapper<MerchantUser> updateWrapper = Wrappers.lambdaUpdate(newMerchantUser);
		updateWrapper.setSql("balance = balance + " + merchantShare);
		merchantUserMapper.update(newMerchantUser, updateWrapper);
		//添加交易记录
		FundDetail buyDetail = createFundDetail(buyer, order, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, now);
		buyDetail.setType(0);
		if (isScan) {
			buyDetail.setBalance(buyer.getBalance());
		} else {
			buyDetail.setBalance(buyer.getBalance().subtract(order.getAmount()));
		}
		buyDetail.setIp(order.getBuyerIp());
		buyDetail.setPaySolution(channelName);
		buyDetail.setChannelShare(channelShare);
		buyDetail.setAlias(alias);
		fundDetailMapper.insert(buyDetail);
		FundDetail sellDetail = createFundDetail(seller, order, merchantShare, platformShare, sellerShare, now);
		sellDetail.setType(1);
		sellDetail.setBalance(seller.getBalance().add(sellerShare));
		sellDetail.setPaySolution(channelName);
		sellDetail.setAlias(alias);
		fundDetailMapper.insert(sellDetail);
		BackSetting setting = backSettingService.findByKey(SystemSettingConstant.CONVERT_TIME);
		if (setting != null && NumberUtil.parseInt(setting.getValue()) > 0) {
			setOrderFrozenAmount(sellerShare, order, NumberUtil.parseInt(setting.getValue()));
		} else {
			FrontUser updateUser = new FrontUser();
			updateUser.setId(order.getSellerId());
			LambdaUpdateWrapper<FrontUser> updates = Wrappers.<FrontUser>lambdaUpdate()
					.setSql("balance = balance + " + sellerShare)
					.eq(FrontUser::getId, order.getSellerId());
			int count = frontUserMapper.update(updateUser, updates);
			if (count < 1) {
				log.warn("更新卖家余额失败, {}", order);
				throw new ServiceException("购买失败");
			}
		}
	}

	private ServiceCharge getCharge(Order order) {
		ServiceCharge charge = new ServiceCharge();
		OrderRate rate = orderRateMapper.selectById(order.getId());
		if (rate == null) {
			MerchantRate r = merchantRateMapper.selectById(order.getUid());
			charge.setChargeRate(r.getChargeRate());
			charge.setChargeSingle(r.getChargeSingle());
			charge.setRateAdditional(r.getRateAdditional());
			charge.setSingleAdditional(r.getSingleAdditional());
			charge.setRateType(r.getRateType());
			charge.setSingleType(r.getSingleType());
			log.info("订单费率为空，应用商户默认费率：{}, 获取的费率信息：{}", r, charge);
			return charge;
		}
		charge.setChargeRate(rate.getChargeRate());
		charge.setChargeSingle(rate.getChargeSingle());
		charge.setRateAdditional(rate.getRateAdditional());
		charge.setSingleAdditional(rate.getSingleAdditional());
		charge.setRateType(rate.getRateType());
		charge.setSingleType(rate.getSingleType());
		log.info("订单费率：{}, 获取的费率信息：{}", rate, charge);
		return charge;
	}
}

